package com.lfy.auth.service.impl;

import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.DigestUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lfy.auth.domain.entity.UserDetailEntity;
import com.lfy.auth.domain.entity.UserEntity;
import com.lfy.auth.domain.msg.RegMsg;
import com.lfy.auth.domain.req.LoginReq;
import com.lfy.auth.domain.req.RegReq;
import com.lfy.auth.domain.resp.LoginResp;
import com.lfy.auth.mapper.UserMapper;
import com.lfy.auth.service.UserDetailService;
import com.lfy.auth.service.UserService;
import com.lfy.chat.client.ChannelCache;
import com.lfy.common.constant.*;
import com.lfy.common.enums.BaseEnum;
import com.lfy.common.result.R;
import com.lfy.common.util.RamdomUtil;
import com.lfy.commons.utils.CookieUtil;
import com.lfy.commons.utils.JwtUtil;
import com.lfy.commons.utils.RedisUtil;
import io.netty.channel.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseCookie;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.time.Duration;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
* @author 吕飞扬
* @description 针对表【user】的数据库操作Service实现
* @createDate 2023-10-12 18:59:53
*/
@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, UserEntity>
    implements UserService {
    @Resource
    private UserMapper userMapper;
    @Resource
    private ApplicationEventPublisher publisher;
    @Resource
    private TransactionTemplate transactionTemplate;
    @Resource
    private UserDetailService userDetailService;
    @Value("${headImgPrefix}")
    private String headImgPrefix;
    /**
     * 注册
     */
    @Override
    public R<Void> reg(RegReq regReq) {
        UserEntity user = new UserEntity();
        user.setPassword(DigestUtil.bcrypt(regReq.getPassword()));
        user.setUserName(regReq.getEmail());


        try {
            this.userMapper.insert(user);
        } catch (Exception e) {
            return R.error(BaseEnum.authEnum.REGISTER_ERROR);
        }
        String uuid = RamdomUtil.getUUID();
        RedisUtil.set(RedisConstant.EMIAL_CONSTANT+uuid,user.getId(),60, TimeUnit.SECONDS);

        RegMsg regMsg = new RegMsg(this,regReq.getEmail(),uuid);
        //发送激活短信
        publisher.publishEvent(regMsg);

        return R.success(BaseEnum.authEnum.REGISTER_SUCCESS);
    }

    /**
     * 激活
     * @param code 激活码
     * @return
     */
    @Override
    public R<Void> activation(String code) {
        String id = null;
        synchronized (this){
             id = RedisUtil.getStr(RedisConstant.EMIAL_CONSTANT + code);
            if(StrUtil.isBlank(id)){
                return R.error(BaseEnum.authEnum.ACTIVATION_ERROR);
            }

            RedisUtil.del(RedisConstant.EMIAL_CONSTANT + code);
        }

        UserEntity userEntity = new UserEntity();
        userEntity.setStatus(BaseEnum.regEnum.AC.getCode());
        UserDetailEntity userDetailEntity = new UserDetailEntity();
        userDetailEntity.setUserId(Long.parseLong(id));
        userDetailEntity.setImg(headImgPrefix.concat("/").concat(DefaultUserConstant.DEFAULT_HEAD_IMG));
        userDetailEntity.setName(DefaultUserConstant.DEFAULT_NAME);
        userDetailEntity.setSignature(DefaultUserConstant.DEFAULT_SIGNATURE);
        String finalId = id;
        Integer result = transactionTemplate.execute(status -> {
            int userAc = this.userMapper.update(userEntity, new LambdaQueryWrapper<UserEntity>().eq(UserEntity::getId, finalId));
            boolean defaultInitUser = this.userDetailService.save(userDetailEntity);
            if(userAc != GlobalConstant.I_1 || !defaultInitUser){
                return null;
            }
            return GlobalConstant.INTEGER_2;
        });
        if(GlobalConstant.INTEGER_2.equals(result)){
            return R.success();
        }
        return R.error(BaseEnum.authEnum.ACTIVATION_ERROR);

    }

    @Override
    public R<LoginResp> login(LoginReq loginReq, HttpServletResponse response) {
        String userName = loginReq.getUserName();
        UserEntity userEntity = this.userMapper.selectOne(new LambdaQueryWrapper<UserEntity>().eq(UserEntity::getUserName, userName));
        if(Objects.isNull(userEntity)){
            return R.error(BaseEnum.authEnum.LOGIN_ERROR);
        }
        String password = userEntity.getPassword();

        if(!DigestUtil.bcryptCheck(loginReq.getPassword(),password) ){
            return R.error(BaseEnum.authEnum.LOGIN_ERROR);
        }
        if(userEntity.getStatus().equals(0)){
            return R.error(BaseEnum.authEnum.NO_ACTIVATION);
        }
        //两处同时登陆，简单处理
        Boolean isLogin = RedisUtil.setNx(ChatReidsConstant.ON_LINE_USER.concat(userEntity.getId().toString()), "1");
        if(!isLogin){
            Channel channel = ChannelCache.getChannel(userEntity.getId().toString());
            ChannelCache.unBinding(channel);
        }

        //TODO 双token
        String jwt = JwtUtil.createJwt(userEntity, 1000 * 60 * 60*6);
        String fastJwt = JwtUtil.createJwt(userEntity, 1000 * 60 * 60);
        log.info("登录的token：{}",jwt);
        CookieUtil.setCookie(null,response, AuthConstant.JWT_HEADER,jwt,1000 * 60 * 60*6);
        CookieUtil.setCookie(null,response, AuthConstant.JWT_FAST_HEADER,fastJwt,1000 * 60 * 60);
        UserDetailEntity userDetail = this.userDetailService.getOne(new LambdaQueryWrapper<UserDetailEntity>().eq(UserDetailEntity::getUserId, userEntity.getId()));
        LoginResp loginResp = new LoginResp();
        BeanUtils.copyProperties(userDetail,loginResp);
        loginResp.setToken(jwt);
//        addCookie(AuthConstant.JWT_HEADER,jwt,response);
        return R.success(BaseEnum.authEnum.LOGIN_SUCCESS,loginResp);
    }
    private void addCookie(String k ,String v,HttpServletResponse response){
        ResponseCookie cookie = ResponseCookie.from(k, v)
                //禁止js获取
                .httpOnly(true)
                //http下传输
                .secure(true)
//                .domain("127.0.0.1")
                // path
                .path("/")
                .maxAge(Duration.ofMillis(30))
                .sameSite("None")
                .build();
        response.setHeader(HttpHeaders.SET_COOKIE,cookie.toString());
    }

    public static void main(String[] args) {
      /*
      * eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyIjp7ImlkIjoyMywidXNlck5hbWUiOiI0MDYxNTQ0M0BxcS5jb
      * 20iLCJwYXNzd29yZCI6IiQyYSQxMCQ1dnN5ZmVvYVZ1SG83a2c2SUhnVVZPeUNDODRPWFg5aDNBUkk3dXNobkdSL3pDMjR2WlVmRyIsInN0YXR1cyI6MSwiY
      * 3JlYXRlVGltZSI6bnVsbCwidXBkYXRlVGltZSI6MTY5N zgwNTMxNTAwMH0sImV4cCI6MTY5ODYwMTM2Mn0.e1ttl8iyM2k4rJwUivXOr1vKlIn2-WQx3qVsrqn0gO4
      * */



    }
}




